home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / networking / amitcp / httpd.lha / httpd / util.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-18  |  12.1 KB  |  571 lines

  1. /*
  2.  * str.c: string utility things
  3.  * 
  4.  * 3/21/93 Rob McCool
  5.  * 
  6.  */
  7.  
  8.  
  9. #include "httpd.h"
  10.  
  11. char *get_time() {
  12.     time_t t;
  13.     char *time_string;
  14.  
  15.     t=time(NULL);
  16.     time_string = ctime(&t);
  17.     time_string[strlen(time_string) - 1] = '\0';
  18.     return (time_string);
  19. }
  20.  
  21. char *gm_timestr_822(time_t sec) {
  22.     struct tm *t;
  23.     static char ts[MAX_STRING_LEN];
  24.  
  25.     t = gmtime(&sec);
  26.     /* check return code? */
  27.     strftime(ts,MAX_STRING_LEN,"%A, %d-%h-%y %T GMT",t);
  28.     return ts;
  29. }
  30.  
  31. void strsubfirst(int start,char *dest, char *src)
  32. {
  33.     char tmp[MAX_STRING_LEN];
  34.  
  35.     strcpy(tmp,&dest[start]);
  36.     strcpy(dest,src);
  37.     strcpy(&dest[strlen(src)],tmp);
  38. }
  39.  
  40. /*
  41.  * Parse .. so we don't compromise security
  42.  */
  43. void getparents(char *name)
  44. {
  45.     int l=0,w=0;
  46.     const char *lookfor="..";
  47. #ifdef AMIGA
  48.     char * cp;
  49. #endif
  50.  
  51.     while(name[l]!='\0') {
  52.         if(name[l]!=lookfor[w]) (w>0 ? (l-=(w-1),w=0) : l++);
  53.         else {
  54.             if(lookfor[++w]=='\0') {
  55.                 if((name[l+1]=='\0') || (name[l+1]=='/')) {
  56.                     register int m=l+1,n;
  57.  
  58.                     l=l-3;
  59.                     if(l>=0) {
  60.                         while((l!=0) && (name[l]!='/')) --l;
  61.                     }
  62.                     else l=0;
  63.                     n=l;
  64.                     while(name[n]=name[m]) (++n,++m);
  65.                     w=0;
  66.                 }
  67.                 else w=0;
  68.             }
  69.             else ++l;
  70.         }
  71.     }
  72. #ifdef AMIGA
  73. /*
  74.  * Allow for AmigaDOS use of / with similar meaning to UNIX ../
  75. */
  76.  
  77.     /* Remove embedded // */
  78.  
  79.     while( cp = strstr( name, "//" ) )
  80.     {
  81.         strcpy( cp, cp + 1 );
  82.     }
  83. #endif
  84. }
  85.  
  86. void make_dirstr(char *s, int n, char *d) {
  87.     register int x,f;
  88.  
  89.     for(x=0,f=0;s[x];x++) {
  90.         if((d[x] = s[x]) == '/')
  91.             if((++f) == n) {
  92.                 d[x] = '\0';
  93.                 return;
  94.             }
  95.     }
  96.     d[x] = '\0';
  97. }
  98.  
  99. int count_dirs(char *path) {
  100.     register int x,n;
  101.  
  102.     for(x=0,n=0;path[x];x++)
  103.         if(path[x] == '/') n++;
  104.     return n;
  105. }
  106.  
  107.  
  108. void strcpy_dir(char *d, char *s) {
  109.     register int x;
  110.  
  111.     for(x=0;s[x];x++)
  112.         d[x] = s[x];
  113.  
  114.     if(s[x-1] != '/') d[x++] = '/';
  115.     d[x] = '\0';
  116. }
  117.  
  118.  
  119. void getline_timed_out() {
  120.     char errstr[MAX_STRING_LEN];
  121.  
  122.     sprintf(errstr,"timed out waiting for %s",remote_name);
  123.     log_error(errstr);
  124.     fclose(stdin);
  125.     fclose(stdout);
  126.     exit(0);
  127. }
  128.  
  129. #ifdef AMIGA
  130. #define read(x,y,z) recv(x,y,z,NULL)
  131. #endif
  132.  
  133. int getline(char *s, int n, int f, unsigned int timeout) {
  134.     register int i=0;
  135.  
  136. #ifndef AMIGA
  137.     signal(SIGALRM,getline_timed_out);
  138. #endif
  139.     alarm(timeout);
  140.     while(1) {
  141.         if(read(f,&s[i],1) <= 0) {
  142.             s[i] = '\0';
  143.             return 1;
  144.         }
  145.  
  146.         if(s[i] == CR)
  147.             read(f,&s[i],1);
  148.  
  149.         if((s[i] == LF) || (i == (n-1))) {
  150.             alarm(0);
  151. #ifndef AMIGA
  152.             signal(SIGALRM,SIG_IGN);
  153. #endif
  154.             s[i] = '\0';
  155.             return 0;
  156.         }
  157.         ++i;
  158.     }
  159. }
  160.  
  161. #ifdef AMIGA
  162. #undef read
  163. #endif
  164.  
  165. void getword(char *word, char *line, char stop) {
  166.     int x = 0,y;
  167.  
  168.     for(x=0;((line[x]) && (line[x] != stop));x++)
  169.         word[x] = line[x];
  170.  
  171.     word[x] = '\0';
  172.     if(line[x]) ++x;
  173.     y=0;
  174.  
  175.     while(line[y++] = line[x++]);
  176. }
  177.  
  178. void cfg_getword(char *word, char *line) {
  179.     int x=0,y;
  180.     
  181.     for(x=0;line[x] && isspace(line[x]);x++);
  182.     y=x;
  183.     while(1) {
  184.         if(!(word[y] = line[x]))
  185.             break;
  186.         if(isspace(line[x]))
  187.             if((!x) || (line[x-1] != '\\'))
  188.                 break;
  189.         if(line[x] != '\\') ++y;
  190.         ++x;
  191.     }
  192.     word[y] = '\0';
  193.     while(line[x] && isspace(line[x])) ++x;
  194.     for(y=0;line[y] = line[x];++x,++y);
  195. }
  196.  
  197. int cfg_getline(char *s, int n, FILE *f) {
  198.     register int i=0;
  199.     register char c;
  200.  
  201.     s[0] = '\0';
  202.     /* skip leading whitespace */
  203.     while(1) {
  204.         c=(char)fgetc(f);
  205.         if((c != '\t') && (c != ' '))
  206.             break;
  207.     }
  208.     while(1) {
  209.         if((c == '\t') || (c == ' ')) {
  210.             s[i++] = ' ';
  211.             while((c == '\t') || (c == ' ')) 
  212.                 c=(char)fgetc(f);
  213.         }
  214.         if(c == CR) {
  215.             c = fgetc(f);
  216.         }
  217.         if((c == 0x4) || (c == LF) || (i == (n-1))) {
  218.             /* blast trailing whitespace */
  219.             while(i && (s[i-1] == ' ')) --i;
  220.             s[i] = '\0';
  221.             return (feof(f) ? 1 : 0);
  222.         }
  223.         s[i] = c;
  224.         ++i;
  225.         c = (char)fgetc(f);
  226.     }
  227. }
  228.  
  229. void plustospace(char *str) {
  230.     register int x;
  231.  
  232.     for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
  233. }
  234.  
  235. void spacetoplus(char *str) {
  236.     register int x;
  237.  
  238.     for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
  239. }
  240.  
  241. char x2c(char *what) {
  242.     register char digit;
  243.  
  244.     digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
  245.     digit *= 16;
  246.     digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
  247.     return(digit);
  248. }
  249.  
  250. void unescape_url(char *url) {
  251.     register int x,y;
  252.  
  253.     for(x=0,y=0;url[y];++x,++y) {
  254.         if((url[x] = url[y]) == '%') {
  255.             url[x] = x2c(&url[y+1]);
  256.             y+=2;
  257.         }
  258.     }
  259.     url[x] = '\0';
  260. }
  261.  
  262. #define c2x(what,where) sprintf(where,"%%%2x",what)
  263.  
  264. void escape_url(char *url) {
  265.     register int x,y;
  266.     register char digit;
  267.     char *copy;
  268.  
  269.     copy = strdup(url);
  270.             
  271.     for(x=0,y=0;copy[x];x++,y++) {
  272.         if(ind("% ?+&",url[y] = copy[x]) != -1) {
  273.             c2x(copy[x],&url[y]);
  274.             y+=2;
  275.         }
  276.     }
  277.     url[y] = '\0';
  278.     free(copy);
  279. }
  280.  
  281. void make_full_path(char *src1,char *src2,char *dst) {
  282.     register int x,y;
  283.  
  284.     for(x=0;dst[x] = src1[x];x++);
  285.  
  286.     if(!x) dst[x++] = '/';
  287.     else if((dst[x-1] != '/'))
  288. #ifdef COLON_SEPARATOR
  289.       if((dst[x-1] != ':'))
  290. #endif
  291.         dst[x++] = '/';
  292.  
  293.     for(y=0;dst[x] = src2[y];x++,y++);
  294. }
  295.  
  296. int is_directory(char *path) {
  297.     struct stat finfo;
  298.  
  299.     if(stat(path,&finfo) == -1)
  300.         return 0; /* in error condition, just return no */
  301.  
  302.     return(S_ISDIR(finfo.st_mode));
  303. }
  304.  
  305. int is_url(char *u) {
  306.     register int x;
  307.  
  308.     for(x=0;u[x] != ':';x++)
  309.         if((!u[x]) || (!isalpha(u[x])))
  310.             return 0;
  311.  
  312.     if((u[x+1] == '/') && (u[x+2] == '/'))
  313.         return 1;
  314.     else return 0;
  315. }
  316.  
  317. void ht_putenv(char *name, char *value) {
  318.     char *t;
  319.  
  320.     t = (char *)malloc(strlen(name)+strlen(value)+2);
  321.     sprintf(t,"%s=%s",name,value);
  322.     putenv(t);
  323. }
  324.  
  325. int can_exec(struct stat *finfo) {
  326.     if(user_id == finfo->st_uid)
  327.         if(finfo->st_mode & S_IXUSR)
  328.             return 1;
  329.     if(group_id == finfo->st_gid)
  330.         if(finfo->st_mode & S_IXGRP)
  331.             return 1;
  332.     return (finfo->st_mode & S_IXOTH);
  333. }
  334.  
  335. #ifdef AMIGA
  336. int can_script(struct stat *finfo) {
  337.     return (finfo->st_mode & S_ISCRIPT);
  338. }
  339. #endif
  340.  
  341. #ifdef NEED_STRDUP
  342. char *strdup (char *str)
  343. {
  344.   char *dup;
  345.  
  346.   dup = (char *)malloc (strlen (str) + 1);
  347.   dup = strcpy (dup, str);
  348.  
  349.   return dup;
  350. }
  351. #endif
  352.  
  353. #ifdef NEED_PUTENV
  354. void putenv(char *s){
  355.     extern char **environ;
  356.     int i;
  357.     char **oldenv;
  358.  
  359.     for(i=0;environ[i]!=NULL;i++) ;
  360.     oldenv = environ;
  361.     environ = (char **) malloc((i+2)*sizeof(char *));
  362.     if(i>0) memcpy(environ, oldenv, i*sizeof(char *));
  363.     environ[i] = s;
  364.     environ[i+1] = NULL;
  365. }
  366. #endif
  367.  
  368.  
  369. #ifdef NEED_INITGROUPS
  370. int initgroups(const char *name, gid_t basegid)
  371. {
  372.   gid_t groups[NGROUPS_MAX];
  373.   struct group *g;
  374.   int index = 0;
  375.  
  376.   groups[index++] = basegid;
  377.  
  378.   while (index < NGROUPS_MAX && ((g = getgrent()) != NULL))
  379.     if (g->gr_gid != basegid)
  380.     {
  381.       char **names;
  382.  
  383.       for (names = g->gr_mem; *names != NULL; ++names)
  384.         if (!strcmp(*names, name))
  385.           groups[index++] = g->gr_gid;
  386.     }
  387.  
  388.   return setgroups(index, groups);
  389. }
  390. #endif
  391.  
  392. int ind(char *s, char c) {
  393.     register int x;
  394.  
  395.     for(x=0;s[x];x++)
  396.         if(s[x] == c) return x;
  397.  
  398.     return -1;
  399. }
  400.  
  401. int rind(char *s, char c) {
  402.     register int x;
  403.  
  404.     for(x=strlen(s)-1;x != -1;x--)
  405.         if(s[x] == c) return x;
  406.  
  407.     return -1;
  408. }
  409.  
  410. void str_tolower(char *str) {
  411.     while(*str) {
  412.         *str = tolower(*str);
  413.         ++str;
  414.     }
  415. }
  416.         
  417. uid_t uname2id(char *name) {
  418.     struct passwd *ent;
  419.  
  420.     if(name[0] == '#') 
  421.         return((uid_t)atoi(&name[1]));
  422.  
  423. #ifndef NO_SECURITY
  424.     if(!(ent = getpwnam(name))) {
  425.         fprintf(stderr,"httpd: bad user name %s\n",name);
  426.         exit(1);
  427.     }
  428.     else return(ent->pw_uid);
  429. #else
  430.     return( 2 );
  431. #endif
  432. }
  433.  
  434. gid_t gname2id(char *name) {
  435.     struct group *ent;
  436.  
  437.     if(name[0] == '#') 
  438.         return(atoi(&name[1]));
  439.  
  440. #ifndef NO_SECURITY
  441.     if(!(ent = getgrnam(name))) {
  442.         fprintf(stderr,"httpd: bad group name %s\n",name);
  443.         exit(1);
  444.     }
  445.     else return(ent->gr_gid);
  446. #else
  447.     return( 2 );
  448. #endif
  449. }
  450.  
  451. int get_portnum(int sd,FILE *out) {
  452.     struct sockaddr addr;
  453.     int len;
  454.  
  455.     len = sizeof(struct sockaddr);
  456.     if(getsockname(sd,&addr,&len) < 0)
  457.         die(SERVER_ERROR,"could not get port number",out);
  458.  
  459.     return(((struct sockaddr_in *)&addr)->sin_port);
  460. }
  461.  
  462. void get_remote_host(int fd) {
  463.     struct sockaddr addr;
  464.     int len;
  465.     struct in_addr *iaddr;
  466.     struct hostent *hptr;
  467.         
  468.     len = sizeof(struct sockaddr);
  469.     
  470.     if ((getpeername(fd, &addr, &len)) < 0) {
  471.         remote_host=NULL;
  472.         remote_ip=NULL;
  473.         remote_name="UNKNOWN_HOST";
  474.         return;
  475.     }
  476.     iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
  477.     hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
  478.     if(hptr) {
  479.         remote_host = strdup(hptr->h_name);
  480.         str_tolower(remote_host);
  481.         remote_name = remote_host;
  482.     }
  483.     else remote_host = NULL;
  484.     
  485.     remote_ip = inet_ntoa(*iaddr);
  486.     if(!remote_host)
  487.         remote_name = remote_ip;
  488. }
  489.  
  490. void get_local_host()
  491. {
  492.     char str[128];
  493.     int len = 128;
  494.  
  495.     if(!server_hostname) {
  496.         struct hostent *p;
  497.         gethostname(str, len);
  498.         if(p=gethostbyname(str))
  499.             server_hostname = strdup(p->h_name);
  500.         else {
  501.             fprintf(stderr,"httpd: cannot determine local host name.\n");
  502.             fprintf(stderr,"Use ServerName to set it manually.\n");
  503.             exit(1);
  504.         }
  505.     }
  506. }
  507.  
  508. void construct_url(char *d, char *s) {
  509.     sprintf(d,"http://%s:%d%s",server_hostname,port,s);
  510.     escape_url(d);
  511. }
  512.  
  513. /* aaaack but it's fast and const should make it shared text page. */
  514. const int pr2six[256]={
  515.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  516.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  517.     52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
  518.     10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  519.     28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  520.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  521.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  522.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  523.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  524.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  525.     64,64,64,64,64,64,64,64,64,64,64,64,64
  526. };
  527.  
  528. void uudecode(char *bufcoded, unsigned char *bufplain, int outbufsize) {
  529.     int nbytesdecoded, j;
  530.     register char *bufin = bufcoded;
  531.     register unsigned char *bufout = bufplain;
  532.     register int nprbytes;
  533.     
  534.     /* Strip leading whitespace. */
  535.     
  536.     while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
  537.     
  538.     /* Figure out how many characters are in the input buffer.
  539.      * If this would decode into more bytes than would fit into
  540.      * the output buffer, adjust the number of input bytes downwards.
  541.      */
  542.     bufin = bufcoded;
  543.     while(pr2six[*(bufin++)] <= 63);
  544.     nprbytes = bufin - bufcoded - 1;
  545.     nbytesdecoded = ((nprbytes+3)/4) * 3;
  546.     if(nbytesdecoded > outbufsize) {
  547.         nprbytes = (outbufsize*4)/3;
  548.     }
  549.     
  550.     bufin = bufcoded;
  551.     
  552.     while (nprbytes > 0) {
  553.         *(bufout++) = 
  554.             (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  555.         *(bufout++) = 
  556.             (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  557.         *(bufout++) = 
  558.             (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  559.         bufin += 4;
  560.         nprbytes -= 4;
  561.     }
  562.     
  563.     if(nprbytes & 03) {
  564.         if(pr2six[bufin[-2]] > 63)
  565.             nbytesdecoded -= 2;
  566.         else
  567.             nbytesdecoded -= 1;
  568.     }
  569.     bufplain[nbytesdecoded] = '\0';
  570. }
  571.